Repository navigation
Add a JSON API to list and create social media snippets - #43
Merged
Merged
Conversation
Since #39 removed the ChatGPT step, nothing writes new social media snippets and there is no API for them. This adds the same Bearer-token JSON API shares already have: GET /links/:link_id/social_media_snippets.json (optional ?social_media_type= filter) POST /links/:link_id/social_media_snippets.json A snippet takes social_media_type (Bluesky, GoogleBusiness, LinkedIn, Mastodon, Twitter), content, and an optional share_id that ties the copy to the tracked short URL it was posted with. share_id is a new nullable reference on social_media_snippets; deleting a share nullifies it. Creating a snippet is rejected with a 422 when the type is missing or unknown, when the same content already exists for that link and type, or when share_id points at a share that doesn't exist or belongs to another link. The type, duplicate, and presence checks run on create only, so snippets saved before this change stay editable. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
The Social Media Snippets section told readers the snippets are created by Open AI. That stopped being true when #39 removed the ChatGPT step, and snippets can now be stored over the JSON API, so it's wrong for new ones too. The copy no longer says where a snippet came from, and points to the shortened links in the Shares section above it. Adds a view spec for the section: snippets are listed under their social media type, the Open AI claim is gone, and the section is left out when a link has no snippets. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
social_media_snippets already has the columns the API needs (social_media_type, content, link_id), so this PR shouldn't change the table. Removes the share_id migration and schema change, the share association and its validations, the share_id param and JSON key, and the specs that covered them. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
etagwerker
marked this pull request as ready for review
November 9, 2026 04:13
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #42.
Since #39 removed the ChatGPT step, nothing writes new social media snippets, and there is no API for them. This gives snippets the same Bearer-token JSON API that shares already have, so a client can store copy next to the article it belongs to. The table already has the columns it needs, so there is no migration.
What it adds
GET /links/:link_id/social_media_snippets.jsonlists a link's snippets, oldest first.?social_media_type=LinkedInnarrows it to one network.POST /links/:link_id/social_media_snippets.jsoncreates one. It takessocial_media_typeandcontent. A JSON body works with or without thesocial_media_snippetwrapper key.ApplicationController, the same waysharesis. A cookie-authenticated browser still gets a 401 on JSON.links/show.html.erb, with a small view spec.Responses follow what shares do:
201with the snippet,422with{ "errors": [...] }.{ "id": 1, "link_id": 7, "social_media_type": "LinkedIn", "content": "...", "created_at": "..." }What gets a 422
social_media_type(it has to be one ofBluesky,GoogleBusiness,LinkedIn,Mastodon,Twitter, spelled that way)contentcontentfor the same link and type, so a client can retry a request safelyThings I'd like a second opinion on
social_media_typeis now required. The model allowed it to be blank before. Copy varies by network (length, style, tone), and the link page groups snippets by network, so one without a network doesn't make sense for new snippets.Share's UTM checks, so existing snippets, whatever their type, can still be edited.Share::UTM_SOURCEShas more networks. Happy to align them if you'd rather.Not in this PR
Updating or deleting snippets, and any HTML view (these endpoints are JSON only).
Testing
bundle exec rspec spec: 83 examples, 0 failures (54 before, 29 new). The request specs cover auth (no token, bad token, cookie only), validation, filtering, and JSON bodies, and a view spec covers the link page section. In the test environment Rails raises for an unknown link (RecordNotFound) or missing params (ParameterMissing) instead of rendering a 404 or 400, so those specs assert the exception.🤖 Generated with Claude Code